package main

import (
	"fmt"
	"strings"
)

// 循环版
func factorial(n int) (result int) {
	if n == 1 {
		return 1
	}
	result = 1
	for i := 2; i <= n; i++ {
		result *= i
	}
	return result
}

// 递归版
func factorialv1(n int) int {
	if n == 1 {
		return 1
	} else {
		return n * factorialv1(n-1)
	}
}

// 2、编写一个函数，接受一个参数n，n为正整数。要求数字必须对齐
func printNum(n int) {
	for i := 1; i <= n; i++ {
		//处理9以内的情况
		if n < 10 {
			// 字符最长个数 2*n - 1, 每层空格数2*n -1 -(2*1 -1)
			count := 2*n - 1
			fmt.Printf(strings.Repeat(" ", count-(2*i-1)))
			for j := i; j >= 1; j-- {
				fmt.Printf("%d ", j)
			}
		} else if n >= 10 && n < 100 {
			// 字符最长个数 2*n + (n % 10)
			count := 2*n + (n % 10)
			if i <= 9 {
				fmt.Printf(strings.Repeat(" ", count-(2*i-1)))
			} else if i >= 10 {
				fmt.Printf(strings.Repeat(" ", count-(2*i+(i%10))))
			}
			for j := i; j >= 1; j-- {
				fmt.Printf("%v ", j)

			}
		}
		fmt.Println()
	}
}

func main() {
	// 1、求n的阶乘。至少使用递归函数完成一次。n=n*(n-1)
	//循环版
	// result := factorial(10)
	// fmt.Println(result)
	//递归版
	// result := factorialv1(10)
	// fmt.Println(result)

	// =============================分割线=============================
	// 2、编写一个函数，接受一个参数n，n为正整数。要求数字必须对齐
	printNum(19)
	// =============================分割线=============================
	// 简述defer作用和应用
	/*
				在函数中，经常需要创建资源（比如：数据库连接、文件句柄、锁等），为了在函数执行完毕后，及时释放资源，Go提供defer（延时机制）
				Go语言中的defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时，将延迟处理的语句按defer定义的逆序进行执行，也就是说，先被defer的语句最后被执行，最后被defer的语句，最先被执行。
				举个例子：
		            func main() {
		                fmt.Println("start")
		                defer fmt.Println(1)
		                defer fmt.Println(2)
		                defer fmt.Println(3)
		                fmt.Println("end")
		        }
				输出结果：
					start
					end
					3
					2
					1
			由于defer语句延迟调用的特性，所以defer语句能非常方便的处理资源释放问题。比如：资源清理、文件关闭、解锁及记录时间等。

			使用细节：
			1）当go执行到一个defer时，不会立即执行defer后的语句，而是将defer后的语句压入到一个栈中
			2）当函数执行完毕后，再从defer栈中，依次从栈顶取出语句执行
			3）在defer将语句放入栈时，也会将相关的值拷贝同时入栈。


	*/
}

